package tests.pl.shenlon.poker.game;

import java.util.ArrayList;
import java.util.List;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;

import pl.shenlon.poker.game.GameState;
import pl.shenlon.poker.game.PlayerActionType;
import pl.shenlon.poker.game.gametypes.NoLimitPokerGame;
import pl.shenlon.poker.game.gametypes.PokerGame;
import tests.pl.shenlon.poker.game.gametypes.MockPokerPlayer;

public class GameStateTest {
	private final int cash = 1000;

	private PokerGame game;

	private GameState gameState;

	@Before
	public void setUp() {
		game = new NoLimitPokerGame();
		game.setPlayerA(new MockPokerPlayer(cash, PlayerActionType.BLUFF, "A"));
		game.setPlayerB(new MockPokerPlayer(cash, PlayerActionType.RAISE, "B"));
		game.dealCards();
		gameState = new GameState(game, game.getPlayerA());
	}

	@Test
	public void testEquals() {
		GameState gameState = new GameState("LOW", "LOW", GameState.ROUND_FLOP,
				true);
		Assert.assertFalse(gameState.equals(null));
		Assert.assertEquals(gameState, gameState);

		Assert.assertEquals(gameState, new GameState("LOW", "LOW",
				GameState.ROUND_FLOP, true));

		GameState otherGameState = new GameState("MEDIUM", "LOW",
				GameState.ROUND_FLOP, true);
		Assert.assertFalse(gameState.equals(otherGameState));
		otherGameState = new GameState("LOW", "MEDIUM", GameState.ROUND_FLOP,
				true);
		Assert.assertFalse(gameState.equals(otherGameState));
		otherGameState = new GameState("LOW", "LOW", GameState.ROUND_PRE_FLOP,
				true);
		Assert.assertFalse(gameState.equals(otherGameState));
		otherGameState = new GameState("LOW", "LOW", GameState.ROUND_FLOP,
				false);
		Assert.assertFalse(gameState.equals(otherGameState));
	}

	@Test
	public void testGetGameRound() {
		game.turnPreFlop();
		Assert.assertEquals(GameState.ROUND_PRE_FLOP,
				GameState.getGameRound(game));

		game.turnFlop();
		Assert.assertEquals(GameState.ROUND_FLOP, GameState.getGameRound(game));

		game.turnTurn();
		Assert.assertEquals(GameState.ROUND_TURN, GameState.getGameRound(game));

		game.turnRiver();
		Assert.assertEquals(GameState.ROUND_RIVER, GameState.getGameRound(game));
	}

	@Test
	public void testGetWinChanceString() {
		Assert.assertEquals("LOW", GameState.getWinChanceString(0.2));
		Assert.assertEquals("MEDIUM", GameState.getWinChanceString(0.5));
		Assert.assertEquals("HIGH", GameState.getWinChanceString(0.8));
		Assert.assertEquals("VERY_HIGH", GameState.getWinChanceString(1.0));
	}

	@Test
	public void testHashCodeUnique() {
		List<Integer> hashCodes = new ArrayList<Integer>();
		for (GameState gameState : GameState.POSSIBLE_GAME_STATES) {
			Assert.assertFalse(hashCodes.contains(gameState.hashCode()));
			hashCodes.add(gameState.hashCode());
		}
	}

	@Test
	public void testIsBetProfitable() {
		Assert.assertTrue(GameState.isBetProfitable(0.1, 0.3, 4, 10));
		Assert.assertTrue(GameState.isBetProfitable(0.0, 0.4, 4, 10));
		Assert.assertTrue(GameState.isBetProfitable(0.4, 0.0, 4, 10));
		Assert.assertTrue(GameState.isBetProfitable(0.1, 0.4, 4, 10));

		Assert.assertFalse(GameState.isBetProfitable(0.1, 0.3, 6, 10));
		Assert.assertFalse(GameState.isBetProfitable(0.0, 0.4, 6, 10));
		Assert.assertFalse(GameState.isBetProfitable(0.4, 0.0, 6, 10));
		Assert.assertFalse(GameState.isBetProfitable(0.1, 0.4, 6, 10));
	}
}
